
const noNested = ['RegExp', 'Date', 'Error', 'Set', 'Map', 'WeakSet', 'WeakMap']
function deepClone(obj, cache = new WeakMap()) {
    if (obj instanceof Object) {
        if (cache.has(obj)) { return cache.get(obj) }
        let result = undefined
        const type = Object.prototype.toString.call(obj).replaceAll(/\[|]|object /g, '')
        if (noNested.includes(type)) {
            return new obj.constructor(obj)
        } else {
            result = new obj.constructor()
            cache.set(obj, result)
            for (const key in obj) {
                if (Object.hasOwnProperty.call(obj, key)) {
                    result[key] = deepClone(obj[key], cache)
                }
            }
            return result
        }
    } else { // 非引用类型
        return obj
    }
}

let obj = {
    name: 1,
    address: { x: 100 },
    arr: [1, 2, 3],
    reg: /$.d/,
    arrSet: new Set([{ p: 1 }, 2, 3]),
    date: new Date(),
    say() {
        console.log('a');
    }
};
obj.orl = obj
/* obj.b = new Date()
obj.b.a = {
    o: 1
} */

const b = deepClone(obj)
obj = null

console.log(b);
console.log(obj);